package activity

import (
	"context"

	"mall/common/globalkey"
	enum "mall/service/backend/common/enum/promotion"
	"mall/service/backend/common/errorx"
	"mall/service/backend/common/i18n"
	"mall/service/promotion/model"
	"mall/service/promotion/rpc/internal/svc"
	"mall/service/promotion/rpc/internal/utils/errorhandler"
	"mall/service/promotion/rpc/types/promotion"

	"github.com/zeromicro/go-zero/core/logx"
)

type BackendCreateActivityCouponLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBackendCreateActivityCouponLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendCreateActivityCouponLogic {
	return &BackendCreateActivityCouponLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *BackendCreateActivityCouponLogic) BackendCreateActivityCoupon(
	in *promotion.ActivityRelationshipInfo,
) (*promotion.BaseResp, error) {
	data, err := l.svcCtx.Activity.FindOneNoCache(l.ctx, nil, in.ActivityId)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	if len(in.Coupons) > 0 {
		var cids []any
		for _, v := range in.Coupons {
			if v.CouponId != nil && *v.CouponId > 0 {
				cids = append(cids, *v.CouponId)
			}
		}

		if len(cids) == 0 {
			return &promotion.BaseResp{
				Msg: i18n.UpdateSuccess,
			}, nil
		}

		filterMap := make(map[string]map[string][]any)
		filterMap[model.PromotionActivityCouponRelationshipColumns.ActivityID] = map[string][]any{
			"equalTo": []any{data.ID},
		}
		filterMap[model.PromotionActivityCouponRelationshipColumns.Status] = map[string][]any{
			"equalTo": []any{globalkey.StatusEnabled},
		}
		filterMap[model.PromotionActivityCouponRelationshipColumns.CouponID] = map[string][]any{
			"in": cids,
		}
		_, count, err := l.svcCtx.Activity.GetCouponList(l.ctx, model.M{}, 0, filterMap)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		// todo: 检查cid的有效性

		if count > 0 {
			return nil, errorx.NewAlreadyExistsError("promotion.activityCouponAlreadyExists")
		}

		tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		var step uint8
		bindRel := &model.PromotionActivityBindRel{}
		for idx, v := range in.Coupons {
			if v.CouponId == nil || *v.CouponId == 0 {
				continue
			}

			step = enum.PromotionActivityStepGift
			var rel model.PromotionActivityCouponRelationship
			rel.ActivityID = data.ID
			rel.ActivityType = data.ActivityType
			rel.CouponID = *v.CouponId

			if v.PerLimit != nil {
				rel.PerLimit = uint8(*v.PerLimit)
			} else {
				rel.PerLimit = uint8(1)
			}
			if v.Sort != nil {
				rel.Sort = uint16(*v.Sort)
			} else {
				rel.Sort = uint16(idx + 1)
			}
			if v.Status != nil {
				rel.Status = uint8(*v.Status)
			} else {
				rel.Status = uint8(globalkey.StatusEnabled)
			}

			bindRel.Coupons = append(bindRel.Coupons, &rel)
		}

		err = l.svcCtx.Activity.UpdateBindRel(l.ctx, tx, data.ID, bindRel)
		if err != nil {
			tx.Rollback()
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		if step > data.CreateStep {
			data.CreateStep = step
			err = l.svcCtx.Activity.Update(l.ctx, tx, data, nil)
			if err != nil {
				tx.Rollback()
				return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
			}
		}

		tx.Commit()
	}

	return &promotion.BaseResp{
		Msg: i18n.UpdateSuccess,
	}, nil
}
